#pragma once
#include "../DefinesCore.hpp"
#include "Log.hpp"
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <stack>

CYBERTRON_BEGIN

class UnlimitedInteger {
public:
	UnlimitedInteger();
	UnlimitedInteger(std::string number);
	UnlimitedInteger(long long number);
	UnlimitedInteger(const UnlimitedInteger& other);

	std::string getString() const;
	size_t digits() const;
	bool isNegative() const;

	friend UnlimitedInteger operator+(UnlimitedInteger u1, const UnlimitedInteger &u2) { return u1.add(u2); }
	friend UnlimitedInteger operator-(UnlimitedInteger u1, const UnlimitedInteger &u2) { return u1.subtract(u2); }
	friend bool operator==(UnlimitedInteger u1, const UnlimitedInteger &u2) { return u1.equals(u2); }
	friend bool operator>(UnlimitedInteger u1, const UnlimitedInteger &u2) { return u1.greater(u2); }
	friend bool operator<(UnlimitedInteger u1, const UnlimitedInteger &u2) { return !u1.greater(u2) && !u1.equals(u2); }
	friend bool operator>=(UnlimitedInteger u1, const UnlimitedInteger &u2) { return (u1.greater(u2) || u1.equals(u2)); }
	friend bool operator<=(UnlimitedInteger u1, const UnlimitedInteger &u2) { return (!u1.greater(u2) || u1.equals(u2)); }
	UnlimitedInteger& operator=(const UnlimitedInteger &other) { _numberString = other._numberString; return *this; }
	UnlimitedInteger& operator+=(const UnlimitedInteger &other) { *this = *this + other; return *this; }
	UnlimitedInteger& operator-=(const UnlimitedInteger &other) { *this = *this - other; return *this; }
	UnlimitedInteger& operator++() { *this += UnlimitedInteger("1"); return *this; }
	UnlimitedInteger& operator--() { *this -= UnlimitedInteger("1"); return *this; }
	UnlimitedInteger negate();

private:
	std::string _numberString;

	bool equals(const UnlimitedInteger &other);
	UnlimitedInteger trimLeadingZeros();
	bool greater(const UnlimitedInteger &u2);
	UnlimitedInteger add(UnlimitedInteger other);
	UnlimitedInteger subtract(UnlimitedInteger other);
};

CYBERTRON_END